/*
 * dictionary.h
 * This file is part of OpenAnimator
 *
 * Copyright (C) 2008 - Abhinav Lele
 *
 * OpenAnimator is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * OpenAnimator is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with OpenAnimator; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, 
 * Boston, MA  02110-1301  USA
 */
 
#include "common.h"
 
#ifndef __OA_DICT_H__
#define __OA_DICT_H__


 
/* cannot use union here for sData and fData */
struct generic_data { unsigned char isNumber; struct { string sData; double fData; } store; };

struct generic_object {
	string name;
	map< double, generic_data> numStore;
	map< string, generic_data, ltstr_stl> stringStore;
	vector< generic_object* > nest;
}; /**< Generic Storage Object */

/**< basic maps required by all objects
 * id, type (string tag), x, y, w, h, _isvisible
 * and following event check functions: isOver(cursorx,cursory), isHit(cursorx,cursory) 
 */


class Dictionary { /**< Storage management class for generic_object */
	public:
		int err; /**< Indicates errors when they occur during get/set operations. On error value is less than zero */
		map< string, generic_object ,ltstr_stl> repository;
		Dictionary();  /**< Initialize repository */
		~Dictionary(); /**< Cleanup all allocations */	
		inline struct generic_object& operator[](string name) { 
			map< string, generic_object, ltstr_stl>::iterator tempiter = repository.find(name); 
			if(tempiter == repository.end()) 
				return (tempiter->second); 
			//else return NULL; 
			throw 1;
		} /* shelved b'cos what to return when not found */
		void add_duplicate(generic_object * src); 
		int LUA_get(lua_State* L); /**< \param object-name \param key-name(number/string) \return <i>Success: </i>value(string/number) <i>Error: </i> No value is returned */
		int LUA_set(lua_State* L); /**< \param object-name \param key-name(number/string) \param new-value(number/string) \return <i>Success: </i>1 <i>Error: </i> No value is returned */
		inline int LUA_new(lua_State *L) { /**< \param object-name \return <i>Success: </i> 1 <i>Error: </i> nothing </i> */
			T("Dict:LUA_new")
			if(lua_isstring(L,ARG1_1)) {
				string name = lua_tostring(L,ARG1_1);
				struct generic_object t;	t.name = name;

				map< string, generic_object ,ltstr_stl>::iterator repository_iter;
				repository_iter = repository.find(name);
				if( repository_iter != repository.end() ) { E("Dict: Item already exists") return 0; }

				repository[name] = t;

				lua_pushnumber(L,1); return 1; 

			}
			return 0;
		}
		inline int LUA_del(lua_State *L) { /**< \param object-name \return <i>Success: </i> 1 <i>Error: </i> nothing </i> */
			T("Dict:LUA_del")
			if(lua_isstring(L,ARG1_1)) {
				string name = lua_tostring(L,ARG1_1);
				map< string, generic_object ,ltstr_stl>::iterator repository_iter;
				repository_iter = repository.find(name);
				if( repository_iter == repository.end() ) { E("Dict: Item does not exist")return 0; }
				repository.erase(repository_iter);
				lua_pushnumber(L,1);
				return 1;
			}
		}
		
		
};

typedef map<string, generic_data, ltstr_stl>::iterator   GENOBJ_SDATAITER;
typedef map<string, generic_object, ltstr_stl>::iterator DICTITER; 

class Library : public Dictionary {};
class Canvas : public Dictionary { 
	public:
		inline int LUA_new(lua_State *L) { T("Canvas:new") return Dictionary::LUA_new(L);  }
};
class Config : public Dictionary {};



#endif
